home *** CD-ROM | disk | FTP | other *** search
-
- *********************************************
- * *
- * *
- * 3D Graphics Library for Blitz Basic II *
- * *
- * *
- * Version 0.9 Beta *
- * *
- * 2B3D (C) 1996 Maciej R. Gorny *
- * *
- *********************************************
-
- CONTENT
-
- 1] HELLO
- 2] 3D COORDINATE SYSTEM
- 3] POLYGONS SUPPORTED
- 4] 3D COMMANDS
- 5] 3D WORLD LIMITS
- 6] DATA STRUCTURES AND NEWTYPES
- 7] PLG - 3D OBJECT FILE FORMAT
- 8] THINGS TO WATCH OUT FOR
- 9] CONTACTING AUTHOR
-
-
-
- 1] HELLO
- _____________________________________________________________________________
-
- My main goal was to have a set of functions (or statements) which would
- allow me to create 3D programs, mainly I was thinking about games here, but not
- only. Well, I run out of time to complete any particular program and this
- set of functions is as far as I got. I haven't been able to test in on
- machine other than mine, which is 68000 powered A2000 with 1.3 Workbench so
- I don't think there should be any problems on other machines.
-
- It is rather modest library. It does not support things like z-buffer, texture
- mapping, or BSP. It simply reads objects in a format transforms between
- different coordinate systems (object's local, world, and camera coordinates)
- and projects the resulting image made up of polygons onto current screen.
- It also performs backface culling to reduce number of polygons projected,
- and either one (z) plane clipping or the entire viewing volume clipping
- (frustum). It also shades the polygons in rather simple manner to give a bit
- more depth and make it look better.
-
- I did not use z-buffer here. I found that scan converting each polygon about to
- be drawn and calculating z-axis values of each pixel in a polygon to be too
- much to handle for my Amiga. Also, Blitz2 does not provide any easy way to
- allocate global array from within a function so the only way I could think of
- to implement z-buffer would be to DIM an array and provide only one z-buffer
- size. Besides, z-buffer uses a lot of memory, so this is a task for later
- updates of the library. The library uses a variant of so called painter's
- algorythm to find out which polygons should be drawn first, and draws them
- in back-to-front order. This solution may cause some problems if there are
- many objects and very close to each other, but with careful planning those
- problems can be avoided.
-
- Once I get this version a bit more optimized, so performance is more acceptable,
- I will add z-buffer functions, as well as better light sourcing functions.
- For example right now it does not matter how far away is a light source located
- from the objects. Also I will add Gouraud shading and maybe even texture
- mapping if I get it to run at decent speeds.
-
- The library is really slow at this stage. That's because this version is
- not completely optimized yet, and most of all is written fully in Blitz2.
- It contains no assembly code whatsoever, due to the fact that I don't know
- anything about 68000 assembly. Some inner loops could probably benefit greatly
- from some assembly, as could the entire library I suppose.
-
- This is the beta release of the software library and as such may contain some
- bugs. If you find any please do not hesitate to contact me and let me know:
-
- Maciej Gorny
- gorn4907@mars.rowan.edu
- or: 424A Victoria Ave.
- Glassboro, NJ 08028, USA
-
- Some of the bugs were especially hard to figure out. RotateObject()
- function for example takes four parameter. Three being the angles and
- another serves as padding of some sort, without which last parameter
- (z-axis angle) had been corrupted. I couldn't find a reason for that, I
- just found the solution which makes RotateObject() work.
-
- If you have any questions, please don't hesitate to send me email or write.
-
-
-
- 2] 3D COORDINATES SYSTEM
- _____________________________________________________________________________
-
- Coordinate system used is a left-handed coordinate system: X-axis goes from left
- to right, Y-axis, from down up-wards, and Z-axis from behind (us) into the
- screen.
-
- ^ +Y
- | Into the screen
- |
- | +Z
- | /
- | /
- | /
- | /
- | /
- |/
- -X ---------------------------> +X
- /|
- / |
- / |
- / |
- / |
- -Z/ |
- |
- Viewer | -Y
-
-
-
-
- 3] POLYGONS SUPPORTED
- _____________________________________________________________________________
-
- 2B3D supports polygons with three vertices (triangles) and the ones with four
- vertices (quads). All other will be either rejected or will cause problems.
- Polygons can be one-sided or two-sided.
-
- One-sided polygons will be visible only when they are facing a viewer. This is
- useful if we want to limit number of polygons rendered to screen by using
- backface culling and remove polygons that cannot be seen in an object. Objects
- cannot concave in such case.
-
- Two-sided polygons will always be rendered to a screen (provided they get
- passed clipping procedures), because they have two sides that are visible to
- a viewer: front and back.
-
-
-
- 4] 3D COMMANDS
- _____________________________________________________________________________
-
- Here's a list of commands in current version of 2B3D Library. A lot of them are
- used internally by the system and end user will never have to use them, but I
- included their descriptions anyway just so maybe someone will find them useful
- somewhere else (like matrix multiplication, or vector math).
-
-
-
- Display3D(w.l, h.l, d.l)
-
- w = current screen width
- h = current screen height
- d = distance from viewer to projection plane
-
- This must be called before any of the 3d functions can be used.
- It precalculates some parameters needed by 3d engine and
- establishes some default setting used bu the system (i.e. light
- source, front and back clipping planes, etc...)
-
- BuildLookUpTables()
-
- Builds look up tables needed by the 3d system. This function is
- automatically called by Display3D. Calling it again by a user
- would be redundant and pointless.
-
- AspectRatio{aspect.f}
-
- aspect = an aspect ratio fraction
-
- This function may be used to change screens aspect ration.
- If a screen is 640x200 squares will look more like rectangles, and
- circles like ovals. Best example of aspect ratio at work is to set
- up your world the way you want it on a display with 1:1 aspect
- ratio (or as close as possible) like 320x200 screen or 640x400.
- Then change the display to something like 640x200 to see the effect.
- I found aspect ratio=0.55 for 640x200 screen adequate and 1.55 for
- screen 320x400.
-
- Call this function to change the default aspect ratio (default=1).
-
- MakeVector3D(a.vertex, b.vertex, r.vector)
-
- Creates a vector (r) out of two vertices a and b.
-
- VectorMag3D(v.vector)
-
- Returns (float) a magnitude of a vector v.
-
- DotProduct(u.vector, v.vector)
-
- Returns (float) a dot product of two vectors.
-
- CrossProduct(u.vector, v.vector, r.vector)
-
- Finds a cross product of two vectors resulting in normal vector.
- Normal vector is the one that is perpendicular to both vectors.
-
- MatIdentity4x4(m.matrix4x4)
-
- Initializes a matrix (m) to become an identity matrix.
-
- MatZero4x4(m.matrix4x4)
-
- Completely empties out a 4x4 matrix (sets it to 0s).
-
- MatCopy4x4(s.matrix4x4, d.matrix4x4)
-
- Copies a 4x4 source matrix (s) into a 4x4 destinatio matrix (d).
-
- MatPrint4x4(m.matrix4x4)
-
- Prints out content of a matrix (m) into output channel.
-
- MatPrint1x4(m.matrix1x4)
-
- Prints out content of a 1x4 matrix (m).
-
- MatMult4x4(m.matrix4x4, n.matrix4x4, r.matri4x4)
-
- Multiplies two 4x4 matrices together (m and n) and stores the result
- in another 4x4 matrix (r).
-
- MatMult4x4S{m.matrix4x4, n.matrix4x4, r.matrix4x4}
-
- This is a special version of MatMult4x4 which is optimized for
- multiplying matrices which contain rotation tranformations.
- It is almost 50% faster than MatMult4x4().
-
- MatMult1x4(a.matrix1x4, b.matrix4x4, r.matrix1x4)
-
- Multiplies a 1x4 matrix (a) and 4x4 matrix (b) and stores the result
- in a 1x4 matrix (r).
-
- PLGGetLine(string.s)
-
- Internal function. Used by PLG loader.
-
- ComputeObjectRadius()
-
- Internal function used by PLG loader.
-
- PLGLoadObject(filename.s, scalar.f)
-
- filename = file location on a disk.
- scalar = scale factor
-
- Loads a 3d object stored in a PLG like file format. An object may
- be scaled as it is loaded by a scale factor. Set scale factor to 1,
- if no scaling is desired.
-
- Objects are loaded into a LIST type array, so most recently loaded
- object becomes currently used object.
-
- ObjectPrint()
-
- Prints out all the information about currently used object.
-
- TranslateObject(dx.l, dy.l, dz.l)
-
- Moves currently used object into a new position in 3d world.
-
- PositionObject(x.l, y.l, z.l)
-
- Positions currently used object in a 3d world space. Should be called
- right after an object is loaded, because by default loaded objects are
- located at (0,0,0) world coordinates.
-
- ScaleObject(s.f)
-
- s = scale factor
-
- Scales currently used object by scale factor.
- if 0<s<1, object will shrink (0.5 is half the size)
- if s=1, no change in object size
- if s>1, object will be enlarged
-
- RotateObject(rx,ry,pad,rz)
-
- rx = degrees around X-axis
- ry = degrees aroumd Y-axis
- rz = degrees around Z-axis
-
- pad= A dummy parameter to avoid Blitz2 corrupting rz parameter.
- This is one of those bugs that I couldn't figure out. Seems
- to work fine this way. I usually pass it as 0.
-
- Rotates currently used object around X,Y, and Z (local) axis.
-
- DrawTopTriangle(p1.pixel, p2.pixel, p3.pixel, color.w)
-
- Draws a triangle with a flat top:
- Serves as an internal function.
- p1______p2
- | /
- | /
- | /
- | /
- | / Points can be in any order.
- | /
- |/p3
-
- DrawBottomTriangle(p1.pixel, p2.pixel, p3.pixel)
-
- Draws a triangle with a flat bottom:
- Serves as an internal function.
- p1
- |\
- | \
- | \ Points can be in any order
- | \
- | \
- | \
- p3|______p2
-
-
- DrawTriangle2D{p1.pixel, p2.pixel, pad.w, p3.pixel)
-
- Draws any triangle with vetices p1, p2, and p3 on a screen.
- pad is necessary to prevent corruption of p3 values.
-
- SetTriangleColor(color)
-
- Sets a color used to draw triangles when using DrawTriangle2D function.
- This parameter was supposed to be passed with the points when calling
- the function, however, it kept corrupting the last point (p3).
- \x and \y values received were different than the ones sent. This seems
- to fix the problem.
-
- ShowObjectWire()
-
- Displays a wireframe representation of a currently used object
- using perspective projection.
-
-
- TouchPalette(first_reg, last_reg, init_color.rgbtype, final_color.rgbtype)
-
- Creates a palette for use with shading functions. Actually, it alters
- existing current screen's palette. It will affect current palette's
- registers between first_reg and last_reg, and it will interpolate
- color values from init_color to final_color.
-
- ex.: I used a 16 color screen (registers 0-15). I wanted to have a
- palette of 16 shades of gray where register 0 contains black,
- and register 15 white color. To achieve this, we should use:
-
- c1.rgbtype\r=0,0,0:c2.rgbtype\r=15,15,15:TouchPalette(0,15,c1,c2)
-
- We also should make sure that objects which use that palette will
- have color field specified to be 0 since shading is added as a
- off of main color.
-
- If we used 32 color screen we could use shades of two colors, i.e.
- shades of grey and red. Registers 0-15 would contain shades of grey,
- and registers 16-31. 16 being deep dark red, and 31 white or very
- bright red. Our polygons could have two colors then: 0 and 16
- specified in the polygon color field.
-
- RemoveBackfacesAndShade()
-
- Removes backfaces (invisible polygons with their back to viewer) and
- calculates shade of their color. Uses current object.
-
- DrawObjectSolid()
-
- Same a ShowObjectWire(), but renders currently used object in its
- solid form.
-
- LocalToWorld()
-
- Translates currently used object's local coordinates to world (global)
- coordinates. Must be used everytime objects position has changed.
-
- WorldToCamera()
-
- Translates currently used object's word coordinates to camera viewing
- coordinates. Must be called every time viewer's position changes or
- object's position changes.
- Used internally.
-
- CreateWorldToCamera()
-
- Creates a global, inverse transformation matrix used to transform world
- coordinates to camera coordinates.
- Used internally.
-
- RemoveObject()
-
- Returns TRUE if currently used object is within viewing volume, FALSE
- otherwise.
-
- DeleteObject()
-
- Removes currently used object from 3d world system.
-
- ClipMode(mode)
-
- Sets the clipping mode for use by the system.
-
- If mode==#FRUSTUM objects will be clipped against the entire
- clipping volume.
-
- If mode==#ZPLANE objects will be clipped only against a
- specified plane on Z axis. This plane is specified in
- Frustum() function as 'near' parameter.
-
- Frustum(near, far)
-
- Defines front and back clipping planes of the viewing volume on a Z
- axis.
-
- CreateLightSource(x,y,z)
-
- Creates a vector describing direction from which rays of light from
- infinite light source are coming. This is very primitive light sourcing
- and the distance of a light source away from the objects has no effect
- on their shading.
-
- PositionCamera(x,y,z)
-
- Places viewer (camera) in a 3d world at specified coordinates.
-
- ViewAngle(angx, angy, angz)
-
- Spefies angle at which a viewer is looking at the 3d world.
- If all angles are 0, viewer is looking straight ahead down
- the positive direction of Z-axis.
-
- ClipObject3D()
-
- Clips currently used object against viewing volume.
-
- GeneratePolyList()
-
- Creates a list of all polygons used in one frame. Must be called before
- using any of the special invisible surface removing fuctions. Also
- must be called whenever objects were added or removed from the 3d world.
- Used internally.
-
- PaintFrame()
-
- Generates a view as seen from viewer's current position. This function
- uses simple implementation of a popular Painter's algorythm to show
- objects in correct order. The function sorts polygons according to their
- maximum z values.
-
- Polygons and objects should not be allowed to intersect each other.
- That's where shortcomings of that algorythm become visible, but
- nevertheless creates some interesting effects I think.
-
- NewView()
-
- Recalculates scenery and prepares it for display using PaintFrame().
- This function should be called every time a scene has changed (i.e.
- viewpoint has been moved, or viewing angle changed, or maybe a new
- object entered a scene).
-
-
- MoveForward(dist)
-
- Moves a viewer forward by 'dist' units (duh!). To move back simply
- enter negative value for dist.
-
- MoveUp(dist)
-
- Relocates a viewer up the Y axis.
-
- MoveDown(dist)
-
- Moves a viewer down the Y axis.
-
- ObjectsUseColor(reg)
-
- Forces all objects in the 3d world to use 'reg' as the base for the
- shading offset. Using TouchPalette() it is possible to specify only
- part of any palette to hold shade variations of some color, and
- using ObjectsUseColor() will force all objects to use our new base
- and the offsets overriding whatever color field was specified in
- object's PLG file.
-
- Example of using it and palette manipulation is in DEMO2.BB2
-
- CameraX(), CameraY(), CameraZ()
-
- All functions return their relevant position in the 3d world.
- They return long word (.l)
-
- AngleX(), AngleY(), AngleZ()
-
- These functions return cameras viewing angles. They return long
- value (.l)
-
-
-
- 5] 3D WORLD LIMITS
- _____________________________________________________________________________
-
- There are some limits involved such as how many vertices one polygon is
- allowed to have, how many polygons are allowed in an object. Here is
- the list:
-
- MAXIMUM LIMIT
- ------------------------------------
- vertices per polygon 4
- polygons per object 32
- vertices per object 128
- objects in 3D world 32
- polygons per frame 1024
- ------------------------------------
-
- That last limit came about as a result of maximum objects allowed in a 3d
- world and how many polygons there is allowed at most for each one of those
- polygons. Of course the more polygons and objects we have to process each
- frame, the slower the whole thing will get.
-
-
-
- 6] DATA STRUCTURES AND NEWTYPES
- _____________________________________________________________________________
-
- Please look at DATASTRUCTS.DOC file for listing of NEWTYPE structures and
- other relevant information.
-
-
-
- 7] PLG OBJECT FILE FORMAT
- _____________________________________________________________________________
-
- This file format is easy enough to understand so anyone can design their own
- objects and write them into a PLG file manually. This library does not support
- PLG files fully, because color information is handled here differently. Other
- than that everything is pretty much as in standard PLG files.
-
- Format is very simple. It contains a list of vertices that comprise an object
- and a list of polygons as well. The first line is a header and contains
- the name of an object followed by number of vertices and number of polygons.
-
- A list of all vertices follows next. Vertices must be presented in x, y, z
- form, with at least one space between each vertex. One vertex per line is
- allowed.
-
- After that a list of polygons follows. One polygon per line is allowed. The
- first number is the color, then number of vertices in this polygon follows,
- followed by list of vertices that compose that polygon.
-
- In real PLG file color information could be decimal or hexadecimal number, but
- this library can read only decimal numbers and that number contains no other
- information other than which register it is in a palette, whatever RGB value
- that may be. So there is no actual RGB value stored there, or shading, or
- special effect information like it would be in an actual PLG file. But that's
- all this library needs. If you would like indicate that a particular polygon
- should be a double sided polygon (that is it will be rendered regardless if
- it is with its front or back to viewer), you only need to add 4096 to the
- color register value. It will set the first bit of the last 4-bit nibble to
- one. The last four bits are supposed to contain additional information about
- a polygon, like special sahding, coloring, effects, etc... Currently 2B3D can
- only read if a polygon is onesided or two sided from that field.
-
- Comments may be placed anywhere in a file. Anything followed by a '#' (number
- sign) or ';' (semicolon) until the end of the line is considered a comment
- and will be ignored by PLG reader.
-
- Look up some .plg files that were included in this archive for examples of the
- format.
-
-
-
- 8] THINGS TO WATCH OUT FOR
- _____________________________________________________________________________
-
- Constant shading is not really supported yet. Objects are expected to use
- flat shading when they are loaded from a .plg file.
-
- Also, the entire objects and polygons get cut from the view if they cross
- clipping planes. Dividing polygons would create polys with more than four
- vertices (which is not supported here) and would further slow down the
- whole thing.
-
-
-
- 9] CONTACTING AUTHOR
- _____________________________________________________________________________
-
- And that is it. This is my little attempt at having written a 3D game in
- Blitz2 and this is as far as I got. Hopefully in the near future I will be
- able to do some more work on this library and expand it further.
-
- If you have any questions, comments, or wish to contact me, send me email at
- gorn4907@mars.rowan.edu or send mail to Maciej Gorny, 424A Victoria Ave.,
- Glassboro, NJ, 08028, USA. I hope you have as much fun using it as I had
- writing it. Take care!
-
- Maciej Gorny
- gorn4907@mars.rowan.edu
- 424A Victoria Avenue
- Glassboro, NJ 08028
- USA
-
- __________________________________________________________________________
- | |
- | BlitzBasic II 3D Graphics Library. Copyright (C) 1996 Maciej R. Gorny. |
- |__________________________________________________________________________|
-
-